﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Gmmy.Utility;
using Gmmy.Utility.Enums;
using Host.Dto;
using Newtonsoft.Json;
using Surging.Core.ApiGateWay.OAuth;
using Surging.Core.Caching;
using Surging.Core.CPlatform.Cache;
using Surging.Core.CPlatform.Ioc;
using Surging.Core.CPlatform.Routing;
using Surging.Core.ProxyGenerator;

namespace Host
{
    public class BaseModule: ServiceBase, IBaseModule
    {

        private readonly IServiceRouteProvider _serviceRouteProvider;
        private readonly ICacheProvider _cacheProvider;
        private readonly IServiceProxyProvider _serviceProxyProvider;
        private readonly TimeSpan _tokenCacheExpire = TimeSpan.FromDays(7);
        private readonly TimeSpan _roleCacheExpire = TimeSpan.FromMinutes(1);
        public BaseModule(IServiceRouteProvider serviceRouteProvider,
            IServiceProxyProvider serviceProxyProvider)
        {
            _serviceRouteProvider = serviceRouteProvider;
            _cacheProvider = CacheContainer.GetService<ICacheProvider>("ddlCache.Redis");
            _serviceProxyProvider = serviceProxyProvider;
        }

        /// <summary>
        /// 私有方法-创建token缓存
        /// </summary>
        /// <param name="data"></param>
        /// <param name="result"></param>
        /// <param name="expire"></param>
        /// <returns></returns>
        public async Task CreateCacheToken(object data, CustomApiResult result)
        {
            var jwtHeader = JsonConvert.SerializeObject(
                new JWTSecureDataHeader() { TimeStamp = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") });
            var base64Payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data)));
            var encodedString = $"{Convert.ToBase64String(Encoding.UTF8.GetBytes(jwtHeader))}.{base64Payload}";
            var route = await _serviceRouteProvider.GetRouteByPath("api/auth/authentication");
            if (route != null)
            {
                var signature = EncryptHelper.GetHMACSHA256(encodedString, route.ServiceDescriptor.Token);
                var token = $"{encodedString}.{signature}";
                result.data = token;
                _cacheProvider.Add(base64Payload, token, _tokenCacheExpire);
            }
        }
        /// <summary>
        /// 私有方法-删除token缓存
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task RemoveTokenCache(string token)
        {
            var check = await CheckTokenCache(token);
            if (check.isSuccess)
            {
                var outtoken = check.jwtToken;
                _cacheProvider.Remove(outtoken[1]);
                _cacheProvider.Remove($"user_info_{outtoken[1]}");
            }
        }

        /// <summary>
        /// 检测缓存是否失效
        /// </summary>
        /// <param name="token"></param>
        /// <param name="jwtToken"></param>
        /// <returns></returns>
        public async Task<CheckTokenCacheDto> CheckTokenCache(string token)
        {
            var result = new CheckTokenCacheDto();
            result.isSuccess = false;
            result.jwtToken = token.Split('.');
            if (result.jwtToken.Length == 3)
            {
                result.isSuccess =await Task.FromResult(_cacheProvider.Get<string>(result.jwtToken[1]) == token);
            }
            return result;
        }

        public async Task<FullLoginInfoDto> GetUserRoleCache(List<string> token)
        {
            var inputparm = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(new
            {
                AuthInfo = Encoding.UTF8.GetString(Convert.FromBase64String(token[1])),
                Token = string.Join("", token),
                RequestInfo = ""
            }));
            return await GetTCache<FullLoginInfoDto>($"user_info_{token[1]}", inputparm, _tokenCacheExpire, "api/User/Info", "User");
        }

        public async Task<List<string>> GetAllModuleAddress(List<string> token)
        {
            var inputparm = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(new
            {
                AuthInfo = Encoding.UTF8.GetString(Convert.FromBase64String(token[1])),
                Token = string.Join("", token),
                RequestInfo = ""
            }));
            return await GetTCache<List<string>>("all_roles", inputparm, _roleCacheExpire, "api/Module/GetModuleAddressAll", "Module");
        }

        /// <summary>
        /// 获取用户权限
        /// </summary>
        /// <param name="key"></param>
        /// <param name="token"></param>
        /// <param name="headkey"></param>
        /// <param name="serviceKey"></param>
        /// <returns></returns>
        public async Task<T> GetTCache<T>(string headkey, object parm, TimeSpan expressTime, string path, string serviceKey)
        {
            var result = _cacheProvider.Get<T>(headkey);
            if (result == null)
            {

                var proxyInput = new Dictionary<string, object> { { "input", parm } };
                var proxyResult =
                    await _serviceProxyProvider.Invoke<CustomApiResult>(proxyInput, path, serviceKey);
                if (proxyResult.code == CustomApiResultCode.Succ)
                {
                    result = JsonConvert.DeserializeObject<T>(
                        JsonConvert.SerializeObject(proxyResult.data));
                    _cacheProvider.Add(headkey, result, expressTime);
                }
                else
                {
                    throw new CustomException(proxyResult.message);
                }
            }
            return result;
        }
    }
}
